Popupmenu v komponente

Otázka od: Roman

27. 11. 2002 21:34

Ahoj,
v komponente odvozene od TDBGrid vytvarim v constructoru vlastni PopupMenu,
kt. zobrazuji po kliknuti pravym tlac. mysi. Polozky menu vytvarim za behu
programu.
Potreboval bych, abych mohl uz v dobe navrhu (tj. pomoci Obj. Insp., kliknu
na "tri tecky" a muzu editovat obsah menu) vytvorit nejake polozky toho
Popupmenu.
Zkousel jsem: published PopupMenuitems:TMenuItem..., ale tudy cesta asi
nevede.
Muzete nekdo poradit jak na to?

Dik,
Roman
- - - - - - - - - - - - - - - - - - - - -
http://kouzelne.misto.cz/

Odpovedá: Ondrej Kelle

28. 11. 2002 10:12

Zdar,

> v komponente odvozene od TDBGrid vytvarim v constructoru
> vlastni PopupMenu, kt. zobrazuji po kliknuti pravym tlac.
> mysi. Polozky menu vytvarim za behu programu.
> Potreboval bych, abych mohl uz v dobe navrhu (tj. pomoci Obj.
> Insp., kliknu na "tri tecky" a muzu editovat obsah menu) vytvorit
> nejake polozky toho Popupmenu.
> Zkousel jsem: published PopupMenuitems:TMenuItem..., ale tudy
> cesta asi nevede.
> Muzete nekdo poradit jak na to?

unika mi pointa celeho Tvojho zameru. Kazdy potomok TControl ma vlastnost
PopupMenu. V pripade TDBGrid je tato vlastnost published, takze je pristupna
v object inspectore. Ako chces riesit konflikt, ked programator priradi
svoje vlastne PopupMenu?
Viem si predstavit, ze by si potreboval v komponente vytvorit nejake default
popupmenu, ktore by sa pouzilo len v pripade, ak nie je vlastnost PopupMenu
priradena (podobne ako je to v pripade TEdit). V tom pripade je to default
popupmenu asi staticke a nema zmysel, aby bolo editovatelne v designeri.
Skus blizsie popisat, co sa snazis dosiahnut.

TOndrej

Odpovedá: Roman

28. 11. 2002 10:40

> Zdar,
>
> > v komponente odvozene od TDBGrid vytvarim v constructoru
> > vlastni PopupMenu, kt. zobrazuji po kliknuti pravym tlac.
> > mysi. Polozky menu vytvarim za behu programu.
> > Potreboval bych, abych mohl uz v dobe navrhu (tj. pomoci Obj.
> > Insp., kliknu na "tri tecky" a muzu editovat obsah menu) vytvorit
> > nejake polozky toho Popupmenu.
> > Zkousel jsem: published PopupMenuitems:TMenuItem..., ale tudy
> > cesta asi nevede.
> > Muzete nekdo poradit jak na to?
>
> unika mi pointa celeho Tvojho zameru. Kazdy potomok TControl ma vlastnost
> PopupMenu. V pripade TDBGrid je tato vlastnost published, takze je
pristupna
> v object inspectore. Ako chces riesit konflikt, ked programator priradi
> svoje vlastne PopupMenu?

Programator nepriradi   a kdyz priradi tak ma smulu.

> Viem si predstavit, ze by si potreboval v komponente vytvorit nejake
default
> popupmenu, ktore by sa pouzilo len v pripade, ak nie je vlastnost
PopupMenu
> priradena (podobne ako je to v pripade TEdit). V tom pripade je to default
> popupmenu asi staticke a nema zmysel, aby bolo editovatelne v designeri.
> Skus blizsie popisat, co sa snazis dosiahnut.

Mam formular, ktery ma nekoliz PageControl s Gridy. Ty Gridy maji vzdy sve
popupmenu, ve kterem jsou vzdy polozky, ktere musi mit kazdy Grid:
zobrazeni sloupcu, nastaveni pisma, barev, vyhledani apod. Ja potrebuju,
abych si pred temi polozkami mohl zadat nejake, ktere jsou jen pro ten
urcity Grid (treba "Novy zaznam", "Tisk upominky"). Za behu programu k nim
pak programove pridam ty ostatni, ktere jsem popsal vyse.
Vim ze bych to mohl resit klasicky (tj. ke kazdemu gridu dam na formular
TPopupMenu), ale uz ted si dovedu predstavit ten zmatek na formulari,
nemluve o tom, ze jedno z tech Popupmenu (pro kazdy Grid) tam bude vzdy
zbytecne.

Roman

Odpovedá: Ondrej Kelle

28. 11. 2002 11:38

>> unika mi pointa celeho Tvojho zameru. Kazdy potomok
>> TControl ma vlastnost PopupMenu. V pripade TDBGrid
>> je tato vlastnost published, takze je pristupna v object
>> inspectore. Ako chces riesit konflikt, ked programator
>> priradi svoje vlastne PopupMenu?
>
> Programator nepriradi   a kdyz priradi tak ma smulu.

Sorry, to je ale proti principom pisania komponent. Komponenty musia byt
kompaktne a blbuvzdorne, inak stracaju svoj zakladny vyznam: setrenie casu a
energie uzivatela - programatora.

> Mam formular, ktery ma nekoliz PageControl s Gridy. Ty Gridy
> maji vzdy sve popupmenu, ve kterem jsou vzdy polozky, ktere
> musi mit kazdy Grid:
> zobrazeni sloupcu, nastaveni pisma, barev, vyhledani apod. Ja
> potrebuju, abych si pred temi polozkami mohl zadat nejake,
> ktere jsou jen pro ten urcity Grid (treba "Novy zaznam", "Tisk
> upominky").
Za behu programu k nim pak programove pridam
> ty ostatni, ktere jsem popsal vyse.
> Vim ze bych to mohl resit klasicky (tj. ke kazdemu gridu dam
> na formular TPopupMenu), ale uz ted si dovedu predstavit ten
> zmatek na formulari, nemluve o tom, ze jedno z tech
> Popupmenu (pro kazdy Grid) tam bude vzdy zbytecne.

Ak som to spravne pochopil, potrebujes mat urcite polozky v popupmenu
spolocne pre kazdy grid a niektore specificke pre jednotlive gridy.
Je na to viacero moznosti, narychlo sem napisem, co ma prave napada:

1. Nadesignovat si jedno popup menu s tymi spolocnymi polozkami a priradit
ho v designeri kazdemu gridu. Potom si napisat kod na OnPopup event, ktory
bude dynamicky vytvarat dalsie polozky, podla aktualneho PopupComponent.
Pripadne sa tieto polozky daju aj nadesignovat ako samostatne popupmenu a v
OnPopup uz len merge-ovat s tym hlavnym.

2. Nadesignovat si jedno popupmenu so vsetkymi moznymi polozkami pre vsetky
gridy a v OnPopup podla aktualneho PopupComponent nastavovat ich Visible
pripadne Enabled.

3. Pouzit TActionList, naplnit ho vsetkymi moznymi akciami pre vsetky gridy,
nadesignovat si popup menu s polozkami ku kazdej akcii, a v OnUpdate menit
Visible pripade Enabled podla toho, na ktorom gride je to popupmenu prave
aktivne.

4. Pouzit frames a form inheritance: vytvorit si zakladny frame s gridom a
popupmenu obsahujucim tie spolocne polozky, a vytvorit si potomkov s
pridanymi dalsimi polozkami, ktore mozu byt potom umiestnene na ten
pagecontrol.

Snad Ta nieco z toho inspiruje,
HTH
TOndrej

Odpovedá: Roman

28. 11. 2002 12:10

> Sorry, to je ale proti principom pisania komponent. Komponenty musia byt
> kompaktne a blbuvzdorne, inak stracaju svoj zakladny vyznam: setrenie casu
a
> energie uzivatela - programatora.

Tohle nema cenu resit, ta komponenta je upravena pro tu konkretni aplikaci,
nikde do sveta nepude. To published Popupmenu bych nejraci zrusil  

> Ak som to spravne pochopil, potrebujes mat urcite polozky v popupmenu
> spolocne pre kazdy grid a niektore specificke pre jednotlive gridy.
> Je na to viacero moznosti, narychlo sem napisem, co ma prave napada:

No tak nejak.

> 1. Nadesignovat si jedno popup menu s tymi spolocnymi polozkami a priradit
> ho v designeri kazdemu gridu. Potom si napisat kod na OnPopup event, ktory
> bude dynamicky vytvarat dalsie polozky, podla aktualneho PopupComponent.
> Pripadne sa tieto polozky daju aj nadesignovat ako samostatne popupmenu a
v
> OnPopup uz len merge-ovat s tym hlavnym.

To je ta sama situace, v jake jsem ted: kazdy grid ma svoje PopUp a navic
musi byt dalsi, ve kterem nadefinuju ty vybrane polozky.

> 2. Nadesignovat si jedno popupmenu so vsetkymi moznymi polozkami pre
vsetky
> gridy a v OnPopup podla aktualneho PopupComponent nastavovat ich Visible
> pripadne Enabled.

Tim ale budu muset predat spravu toho Gridu nekam mimo samotnou komponentu
(protoze polozky pro nastavovani gridu by byly v Popupmenu nekde na
formulari).

> 3. Pouzit TActionList, naplnit ho vsetkymi moznymi akciami pre vsetky
gridy,
> nadesignovat si popup menu s polozkami ku kazdej akcii, a v OnUpdate menit
> Visible pripade Enabled podla toho, na ktorom gride je to popupmenu prave
> aktivne.

Stejne jako 2.

> 4. Pouzit frames a form inheritance: vytvorit si zakladny frame s gridom a
> popupmenu obsahujucim tie spolocne polozky, a vytvorit si potomkov s
> pridanymi dalsimi polozkami, ktore mozu byt potom umiestnene na ten
> pagecontrol.

To to by bylo reseni, kdybych zacinal od zacatku. Jenze ja potrebuju
rozsirit funkcnost stavajici komponenty.

Me prijde nejrozumejsi, aby ten Grid mel published property MenuItems:
TMenuItem.
Tj. zadam tam v OI nejake polozky, ktera pak programove doplnim do nejakeho
Popupmenu (at uz vytvoreneho v constructoru Gridu nebo prirazeneho v
PopupMenu). Muj problem je, ze nevim, jak docilit zobrazeni toho
"navrhare
menu" pro tuto property v design modu.

Dik za odpovedi,
Roman
==============================
http://kouzelne.misto.cz

Odpovedá: Ondrej Kelle

28. 11. 2002 15:20

> Tohle nema cenu resit, ta komponenta je upravena pro tu
> konkretni aplikaci, nikde do sveta nepude. To published
> Popupmenu bych nejraci zrusil  

Mozes si svoju komponentu odvodit od TCustomDBGrid a publikovat len tie
vlastnosti, ktore uznas za vhodne.

>> 1. Nadesignovat si jedno popup menu s tymi spolocnymi
>> polozkami a priradit ho v designeri kazdemu gridu. Potom
>> si napisat kod na OnPopup event, ktory bude dynamicky
>> vytvarat dalsie polozky, podla aktualneho
>> PopupComponent. Pripadne sa tieto polozky daju aj
>> nadesignovat ako samostatne popupmenu a v OnPopup
>> uz len merge-ovat s tym hlavnym.
>
> To je ta sama situace, v jake jsem ted: kazdy grid ma svoje
> PopUp a navic musi byt dalsi, ve kterem nadefinuju ty vybrane
> polozky.

Vobec nie. V mnou navrhovanom pripade mas iba jedine popupmenu na formulari,
a to je priradene vlastnosti PopupMenu kazdeho gridu.

>> 2. Nadesignovat si jedno popupmenu so vsetkymi moznymi polozkami pre
>> vsetky gridy a v OnPopup podla aktualneho PopupComponent nastavovat
>> ich Visible pripadne Enabled.
>
> Tim ale budu muset predat spravu toho Gridu nekam mimo samotnou
> komponentu (protoze polozky pro nastavovani gridu by byly v Popupmenu
> nekde na formulari).

Presne tak. Podla toho, co si napisal, totiz ziadny vseobecny komponent
nepotrebujes, staci Ti riesenie na urovni formulara alebo projektu.

>> 4. Pouzit frames a form inheritance: vytvorit si zakladny frame s gridom
a
>> popupmenu obsahujucim tie spolocne polozky, a vytvorit si potomkov s
>> pridanymi dalsimi polozkami, ktore mozu byt potom umiestnene na ten
>> pagecontrol.
>
> To to by bylo reseni, kdybych zacinal od zacatku. Jenze ja potrebuju
> rozsirit funkcnost stavajici komponenty.
>
> Me prijde nejrozumejsi, aby ten Grid mel published property MenuItems:
> TMenuItem. Tj. zadam tam v OI nejake polozky, ktera pak programove
> doplnim do nejakeho Popupmenu (at uz vytvoreneho v constructoru Gridu
> nebo prirazeneho v PopupMenu). Muj problem je, ze nevim, jak docilit
> zobrazeni toho "navrhare menu" pro tuto property v design modu.

Podla mna to nie je rozumne ani trochu. Okrem toho je to tazko (ak vobec)
implementovatelne a pritom uplne zbytocne.
Predpokladam, ze kod, ktory sa ma vykonat pri zvoleni polozky budes pisat v
OnClick handleri na urovni parent formulara. A v tom pripade je uplne
zbytocne "schovavat" nejake TMenuItem do nejakej komponenty.

Zobrazenie navrhara menu nie je az taky problem (v designtime balicku):

procedure Register;
begin
  RegisterComponents('Tests', [TMyDBGrid]);
  RegisterPropertyEditor(TypeInfo(TMenuItem), TMyDBGrid, 'MenuItems',
TMenuItemProperty);
end;

Druha vec je, ze zobrazenie menu editora Ti nebude asi nic platne. Ten menu
editor vklada deklaracie jednotlivych TMenuItem priamo do zdrojaku triedy
formulara. Triedy TMenu a TMenuItem neboli pisane pre taketo pouzitie;
vsimni si, ze TMenu publikuje natvrdo Items typu TMenuItem a TMenuItem tak
isto. Nie je mozne zdedenim potrebne upravit funkcionalitu pre korektne
streamovanie do .dfm v kontexte Tvojho gridu (a nie formulara - ono to totiz
ani nedava zmysel). A v pripade, ze si napises vlastne triedy, zase
nepouzijes ten default menu editor a musis si napisat svoj vlastny.
V kazdom pripade, odporucam Ti poriadne si premysliet, co vlastne chces a
preco to chces.
Ale ak mi snad nieco uslo, rad sa necham poucit.

HTH
TOndrej